import React from 'react';
import { createFragmentContainer, graphql } from 'react-relay';
import { Field, Form, Formik } from 'formik';
import * as Yup from 'yup';
import MenuItem from '@mui/material/MenuItem';
import { vulnerabilityEditionOverviewFocus, vulnerabilityMutationRelationAdd, vulnerabilityMutationRelationDelete } from './VulnerabilityEditionOverview';
import { useFormatter } from '../../../../components/i18n';
import TextField from '../../../../components/TextField';
import { SubscriptionFocus } from '../../../../components/Subscription';
import SelectField from '../../../../components/fields/SelectField';
import { adaptFieldValue } from '../../../../utils/String';
import CommitMessage from '../../common/form/CommitMessage';
import { fieldSpacingContainerStyle } from '../../../../utils/field';
import useFormEditor from '../../../../utils/hooks/useFormEditor';
import { useSchemaEditionValidation } from '../../../../utils/hooks/useEntitySettings';
import AlertConfidenceForEntity from '../../../../components/AlertConfidenceForEntity';
import SwitchField from '../../../../components/fields/SwitchField';

const vulnerabilityMutationFieldPatch = graphql`
  mutation VulnerabilityEditionDetailsFieldPatchMutation(
    $id: ID!
    $input: [EditInput]!
    $commitMessage: String
    $references: [String]
  ) {
    vulnerabilityEdit(id: $id) {
      fieldPatch(
        input: $input
        commitMessage: $commitMessage
        references: $references
      ) {
        ...VulnerabilityEditionDetails_vulnerability
        ...Vulnerability_vulnerability
      }
    }
  }
`;

const VulnerabilityEditionDetailsComponent = (props) => {
  const { vulnerability, enableReferences, context, handleClose } = props;
  const { t_i18n } = useFormatter();

  const basicShape = {
    x_opencti_cvss_base_score: Yup.number().min(0).max(10).nullable(),
    x_opencti_cvss_base_severity: Yup.string().nullable(),
    x_opencti_cvss_attack_vector: Yup.string().nullable(),
    x_opencti_cvss_integrity_impact: Yup.string().nullable(),
    x_opencti_cvss_availability_impact: Yup.string().nullable(),
    x_opencti_cvss_confidentiality_impact: Yup.string().nullable(),
    x_opencti_cisa_kev: Yup.boolean().nullable(),
    x_opencti_epss_score: Yup.number().min(0).max(1).nullable(),
    x_opencti_epss_percentile: Yup.number().min(0).max(1).nullable(),
  };

  const vulnerabilityValidator = useSchemaEditionValidation('vulnerability', basicShape);

  const queries = {
    fieldPatch: vulnerabilityMutationFieldPatch,
    relationAdd: vulnerabilityMutationRelationAdd,
    relationDelete: vulnerabilityMutationRelationDelete,
    editionFocus: vulnerabilityEditionOverviewFocus,
  };

  const editor = useFormEditor(
    vulnerability,
    enableReferences,
    queries,
    vulnerabilityValidator,
  );

  const onSubmit = (values, { setSubmitting }) => {
    const { message, references, ...otherValues } = values;
    const commitMessage = message ?? '';
    const commitReferences = (references ?? []).map(({ value }) => value);
    const inputValues = Object.entries({
      ...otherValues,
      createdBy: values.createdBy?.value,
      x_opencti_cvss_base_score: parseFloat(values.x_opencti_cvss_base_score),
      x_opencti_workflow_id: values.x_opencti_workflow_id?.value,
      objectMarking: (values.objectMarking ?? []).map(({ value }) => value),
    }).map(([key, value]) => ({ key, value: adaptFieldValue(value) }));
    editor.fieldPatch({
      variables: {
        id: vulnerability.id,
        input: inputValues,
        commitMessage:
          commitMessage && commitMessage.length > 0 ? commitMessage : null,
        references: commitReferences,
      },
      setSubmitting,
      onCompleted: () => {
        setSubmitting(false);
        handleClose();
      },
    });
  };

  const handleSubmitField = (name, value) => {
    if (!enableReferences) {
      vulnerabilityValidator
        .validateAt(name, { [name]: value })
        .then(() => {
          editor.fieldPatch({
            variables: {
              id: vulnerability.id,
              input: [{ key: name, value: value ?? [null] }],
            },
          });
        })
        .catch((error) => error);
    }
  };

  const initialValues = {
    x_opencti_cvss_base_score: vulnerability.x_opencti_cvss_base_score,
    x_opencti_cvss_base_severity: vulnerability.x_opencti_cvss_base_severity,
    x_opencti_cvss_attack_vector: vulnerability.x_opencti_cvss_attack_vector,
    x_opencti_cvss_integrity_impact: vulnerability.x_opencti_cvss_integrity_impact,
    x_opencti_cvss_availability_impact: vulnerability.x_opencti_cvss_availability_impact,
    x_opencti_cvss_confidentiality_impact: vulnerability.x_opencti_cvss_confidentiality_impact,
    x_opencti_cisa_kev: vulnerability.x_opencti_cisa_kev,
    x_opencti_epss_score: vulnerability.x_opencti_epss_score,
    x_opencti_epss_percentile: vulnerability.x_opencti_epss_percentile,
  };

  return (
    <Formik
      enableReinitialize={true}
      initialValues={initialValues}
      validationSchema={vulnerabilityValidator}
      onSubmit={onSubmit}
    >
      {({
        submitForm,
        isSubmitting,
        setFieldValue,
        values,
        isValid,
        dirty,
      }) => (
        <Form style={{ margin: '20px 0 20px 0' }}>
          <AlertConfidenceForEntity entity={vulnerability} />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_cvss_base_score"
            label={t_i18n('CVSS3 - Score')}
            fullWidth={true}
            type="number"
            step="0.1"
            onFocus={editor.changeFocus}
            onSubmit={(name, value) => handleSubmitField(name, (value === '' ? null : value))}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_base_score"
              />
            }
          />
          { /* TODO Dont touch until CVSS4 */ }
          <Field
            component={SelectField}
            variant="standard"
            name="x_opencti_cvss_base_severity"
            label={t_i18n('CVSS3 - Severity')}
            fullWidth={true}
            containerstyle={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onChange={handleSubmitField}
            helpertext={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_base_severity"
              />
            }
          >
            <MenuItem value="CRITICAL">{t_i18n('CRITICAL')}</MenuItem>
            <MenuItem value="HIGH">{t_i18n('HIGH')}</MenuItem>
            <MenuItem value="MEDIUM">{t_i18n('MEDIUM')}</MenuItem>
            <MenuItem value="LOW">{t_i18n('LOW')}</MenuItem>
            <MenuItem value="Unknown">{t_i18n('Unknown')}</MenuItem>
          </Field>
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_cvss_attack_vector"
            label={t_i18n('CVSS3 - Attack vector')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_attack_vector"
              />
            }
          />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_cvss_integrity_impact"
            label={t_i18n('CVSS3 - Integrity impact')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_integrity_impact"
              />
            }
          />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_cvss_availability_impact"
            label={t_i18n('CVSS3 - Availability impact')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_availability_impact"
              />
            }
          />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_cvss_confidentiality_impact"
            label={t_i18n('CVSS3 - Confidentiality impact')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cvss_confidentiality_impact"
              />
            }
          />
          <Field
            component={SwitchField}
            type="checkbox"
            name="x_opencti_cisa_kev"
            label={t_i18n('CISA KEV')}
            fullWidth
            onFocus={editor.changeFocus}
            onChange={handleSubmitField}
            containerstyle={{ marginTop: 20 }}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_cisa_kev"
              />
            }
          />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_epss_score"
            label={t_i18n('EPSS Score')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_epss_score"
              />
            }
          />
          <Field
            component={TextField}
            variant="standard"
            name="x_opencti_epss_percentile"
            label={t_i18n('EPSS Percentile')}
            fullWidth={true}
            style={fieldSpacingContainerStyle}
            onFocus={editor.changeFocus}
            onSubmit={handleSubmitField}
            helperText={
              <SubscriptionFocus
                context={context}
                fieldName="x_opencti_epss_percentile"
              />
            }
          />
          {enableReferences && (
            <CommitMessage
              submitForm={submitForm}
              disabled={isSubmitting || !isValid || !dirty}
              setFieldValue={setFieldValue}
              open={false}
              values={values.references}
              id={vulnerability.id}
            />
          )}
        </Form>
      )}
    </Formik>
  );
};

export default createFragmentContainer(VulnerabilityEditionDetailsComponent, {
  vulnerability: graphql`
      fragment VulnerabilityEditionDetails_vulnerability on Vulnerability {
        id
        x_opencti_cvss_base_score
        x_opencti_cvss_base_severity
        x_opencti_cvss_attack_vector
        x_opencti_cvss_integrity_impact
        x_opencti_cvss_availability_impact
        x_opencti_cvss_confidentiality_impact
        x_opencti_cisa_kev
        x_opencti_epss_score
        x_opencti_epss_percentile
        confidence
        entity_type
      }
    `,
});
